/*
 * @Author: 13938960424 1758142861@qq.com
 * @Date: 2023-10-25 17:44:11
 * @LastEditors: 13938960424 1758142861@qq.com
 * @LastEditTime: 2023-10-25 17:48:15
 * @FilePath: /sjf/new-xshell/muduo/pre_knowledge/any_test.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <string>
#include <typeinfo>
#include <cassert>

class Any
{
public:
    Any():_content(nullptr)
    {}
    template<class T>
    Any(const T& val) 
    :_content(new placeholder<T>(val))
    {}
    Any(const Any& other) 
    :_content(other._content ? other._content->clone() : nullptr)
    {}
    ~Any() { delete _content;};
    //交换函数
    Any &swap(Any &other)
    {
        std::swap(_content,other._content);
        return *this;
    }
    //获取子类独享保存数据的指针
    template<class T>
    T* get() 
    {
        assert(typeid(T) == _content->type());
        return &((placeholder<T>*)_content)->_val;
    }
    //赋值运算符的重载
    template<class T>
    Any& operator=(const T& val) 
    {
        /**
         * Any(val).swap(*this);
         * 表示的是val构造一个临时的通用容器
         * 然后于当前容器自身进行指针交换
         * 临时对象释放的时候，原先保存的数据也就被释放了
        */
        Any(val).swap(*this);
        return *this;
    }
    Any& operator=(const Any& other) 
    {
        Any(other).swap(*this);
        return *this;
    }

private:
    class holder
    {
    public:
        virtual ~holder() {}
        virtual const std::type_info& type() = 0;
        virtual holder *clone() = 0;
    };
    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val) : _val(val)
        {
        }
        //获得子类对象保存的数据类型
        virtual const std::type_info& type() { return typeid(T); }
        //针对当前的对象自身，克隆出一个新的子类对象
        virtual holder *clone() { return new placeholder(_val); }

    public:
        T _val;
    };
    holder *_content;
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }
    Test(const Test& t) { std::cout << "拷贝构造" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

int main()
{
    Any a;
    a = 10;
    int *pa = a.get<int>();
    std::cout << *pa << std::endl;
    a = std::string("any test");
    std::string *ps = a.get<std::string>();
    std::cout << *ps << std::endl;

    Any t;
    {
        Test tt;
        t = tt;
    }
    return 0;
}